package com.md.api.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.gson.Gson;
import com.kuaidi100.sdk.api.QueryTrack;
import com.kuaidi100.sdk.core.IBaseClient;
import com.kuaidi100.sdk.request.QueryTrackParam;
import com.kuaidi100.sdk.request.QueryTrackReq;
import com.kuaidi100.sdk.response.QueryTrackData;
import com.kuaidi100.sdk.response.QueryTrackResp;
import com.kuaidi100.sdk.utils.SignUtils;
import com.md.api.common.config.RedisKeys;
import com.md.api.common.exception.BusinessException;
import com.md.api.common.utils.*;
import com.md.api.dao.*;
import com.md.api.entity.*;
import com.md.api.entity.dto.ComposeCommitDto;
import com.md.api.entity.dto.ComposeQueryDto;
import com.md.api.entity.enums.*;
import com.md.api.entity.util.Page;
import com.md.api.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Author liujie
 * @ClassName ShoppingCartServiceImpl
 **/

@Slf4j
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {
    @Value("${wx.pay.backShoppingNotifyUrl}")
    private String backShoppingNotifyUrl;
    @Value("${wx.pay.shoppingNotifyUrl}")
    private String shoppingNotifyUrl;
    @Value("${kuaidi100.key}")
    private String key;
    @Value("${kuaidi100.customer}")
    private String customer;
    @Resource
    ShoppingSkuMapper shoppingSkuMapper;
    @Resource
    ShoppingSpuMapper spuMapper;
    @Resource
    RedisUtil redisUtil;
    @Resource
    UserMessageMapper userMessageMapper;
    @Resource
    RedissonClient redisson;
    @Resource
    TokenUtil tokenUtil;
    @Resource
    UserCouponRecordMapper couponRecordMapper;
    @Resource
    ShoppingRefundOrderMapper shoppingRefundOrderMapper;
    @Resource
    UserMapper userMapper;
    @Resource
    ShoppingSpuEvaluateMapper evaluateMapper;
    @Resource
    ShoppingOrderMapper shoppingOrderMapper;
    @Resource
    ShoppingOrderDetailMapper shoppingOrderDetailMapper;
    @Resource
    ReceivingAddrInfoMapper addrInfoMapper;
    @Resource
    ShoppingCartMapper shoppingCartMapper;
    @Resource
    UserPointRecordMapper pointRecordMapper;
    @Resource
    private WxPayService wxService;
    @Resource
    ShoppingRefundOrderMapper refundOrderMapper;
    @Resource
    ShoppingChangeOrderMapper changeOrderMapper;
    @Resource
    UserBalanceRecordMapper balanceRecordMapper;

    @Override
    public HttpResult addShoppingCart(HttpServletRequest request, ShoppingCart shoppingCart) {
        String userId = tokenUtil.getUserId(request);
        String cartId = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
        shoppingCart.setCartId(cartId);
        shoppingCart.setUserId(userId);
        shoppingCartMapper.insert(shoppingCart);
        return HttpResult.OK;
    }

    @Override
    public HttpResult myShoppingCart(HttpServletRequest request, ComposeQueryDto qto) {
        Page page = qto.getPage();
        page.initPagingData(MyShopCart.class);
        String userId = tokenUtil.getUserId(request);
//        String userId = request.getHeader("userId");
        List<MyShopCart> cartList = shoppingCartMapper.myCart(userId);
        page.setResult(cartList);
        return new HttpResult(page);
    }

    @Override
    public HttpResult removeShoppingCart(HttpServletRequest request, ComposeCommitDto qto) {
        shoppingCartMapper.deleteById(qto.getCartId());
        return HttpResult.OK;
    }

    @Override
    public HttpResult resetProductCount(HttpServletRequest request, ComposeCommitDto qto) {
        shoppingCartMapper.resetProductCount(qto.getCartId(),qto.getCount());
        return HttpResult.OK;
    }

    @Override
    public HttpResult shoppingCartTrade(HttpServletRequest request, ComposeCommitDto qto) {
        Map resultMap = new HashMap();
        BigDecimal totalMoney = new BigDecimal("0");
        BigDecimal totalPay = new BigDecimal("0");
        BigDecimal totalPoint = new BigDecimal("0");
        BigDecimal discount = new BigDecimal("1");
        String discountStr = "";
        String discountFrom = "";
        //TODO 当前购物车中所有的产品及数量
        String userId = tokenUtil.getUserId(request);
        List<MyShopCart> myCarts = new ArrayList<>();
        if (CollectionUtil.isEmpty(qto.getCartIds())){//默认购物车所有
            myCarts = shoppingCartMapper.myCart(userId);
            if (CollectionUtil.isEmpty(qto.getCartIds())) {//购物车为空，不计算
                resultMap.put("totalMoney",totalMoney.doubleValue());
                resultMap.put("totalPay",totalPay.doubleValue());
                resultMap.put("totalPoint",totalPoint.doubleValue());
                return new HttpResult(resultMap);
            }
        }else{
            myCarts = shoppingCartMapper.getSkuByCartIds(qto.getCartIds());
        }
        for (MyShopCart cart:myCarts){
            if (cart.getSaleStatus()!=SaleStatus.LISTING.value()){
                return HttpResult.fail("购物车中存在已下架商品！");
            }
            BigDecimal price = BigDecimalUtil.mul(null != cart.getDiscountPrice() ? cart.getDiscountPrice() : cart.getOrginPrice(),cart.getNumCount());
            totalMoney = totalMoney.add(price);
        }
        //使用优惠券特别折扣
        if (StringUtils.isNotEmpty(qto.getCouponRecordId())){
            //校验折扣券是否可用，防止爬虫通过过期券调用
            UserCouponRecord couponRecord = couponRecordMapper.getByCouponRecordId(qto.getCouponRecordId());
            if (couponRecord.getUseWay()==1){
                return HttpResult.fail("该券不是车检优惠券！");
            }
            Integer couponWay = couponRecord.getCouponWay();
            discount = new BigDecimal(new Double(couponRecord.getDiscount()).toString());
            if (couponWay==1){//折扣券
                discountStr = "享折扣券"+discount.doubleValue()*10+"折优惠";
                discountFrom = "折扣券优惠";
                totalPay = totalPay.add(totalMoney.multiply(discount));
                resultMap.put("discount",NumberUtils.numFormat(discount.doubleValue()));
                resultMap.put("discountType",1);
            }else if (couponWay==2){//现金券
                totalPay = totalPay.add(totalMoney.subtract(discount));
                discountStr = "享现金券"+discount.doubleValue()+"元优惠";
                discountFrom = "现金券优惠";
                resultMap.put("discountType",2);
            }else{//满减券
                //最低金额是否达到
                if(totalMoney.doubleValue()<couponRecord.getLowerMoney()){
                    return HttpResult.fail("未达到满减券最低消费金额！");
                }
                totalPay = totalPay.add(totalMoney.subtract(discount));
                discountStr = "享现金券"+discount.doubleValue()+"元优惠";
                discountFrom = "现金券优惠";
                resultMap.put("discountType",2);
            }
        }else{//按照会员折扣计算
            totalPay = new BigDecimal(totalMoney.doubleValue());
        }
        if (StringUtils.isNotEmpty(discountStr)) {
            Double discountMoney = totalMoney.subtract(totalPay).doubleValue();
            resultMap.put("discountMoney",NumberUtils.numFormat(discountMoney));
            resultMap.put("discountStr",discountStr);
            resultMap.put("discountFrom",discountFrom);
        }
        resultMap.put("discount",NumberUtils.numFormat(discount.doubleValue()));
        resultMap.put("totalMoney",NumberUtils.numFormat(totalMoney.doubleValue()));
        resultMap.put("totalPay",NumberUtils.numFormat(totalPay.doubleValue()));
        return new HttpResult(resultMap);
    }


    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public HttpResult orderShoppingCart(HttpServletRequest request, ComposeCommitDto buyDto) throws WxPayException {
        String userId = tokenUtil.getUserId(request);
        List<MyShopCart> myCarts = new ArrayList<>();
        if (CollectionUtil.isEmpty(buyDto.getCartIds())){//默认购物车所有
            myCarts = shoppingCartMapper.myCart(userId);
        }else{
            myCarts = shoppingCartMapper.getSkuByCartIds(buyDto.getCartIds());
        }
        for (MyShopCart cart:myCarts){
            if (cart.getSaleStatus()!=SaleStatus.LISTING.value()){
                return HttpResult.fail("购物车中存在已下架商品！");
            }
        }

        UserInfo user = userMapper.getByUserId(userId);
        HttpResult httpResult = this.shoppingCartTrade(request, buyDto);
        Map resultMap = (Map)httpResult.getData();
        String discountStr = null!=resultMap.get("discountStr")?resultMap.get("discountStr").toString():"";
        Double discountMoney = null!=resultMap.get("discountMoney")?Double.valueOf(resultMap.get("discountMoney").toString()):null;
        Double totalMoney = null!=resultMap.get("totalMoney")?Double.valueOf(resultMap.get("totalMoney").toString()):null;
        Double totalPay = null!=resultMap.get("totalPay")?Double.valueOf(resultMap.get("totalPay").toString()):null;
        Double discount = null!=resultMap.get("discount")?Double.valueOf(resultMap.get("discount").toString()):null;
        Integer discountType = null!=resultMap.get("discountType")?Integer.valueOf(resultMap.get("discountType").toString()):null;
        if (totalPay<0){
            return HttpResult.fail("您还未添加购物车，请确认！");
        }
        //创建订单号
        String code = CodeUtil.verifyCode(6);
        String today = DateUtil.format(new Date(), "yyyyMMdd");
        String orderNo = "so".concat(today).concat(code);

        ShoppingOrder order = new ShoppingOrder();
        order.setOrderNo(orderNo);
        if (StringUtils.isNotEmpty(buyDto.getReceivingAddrId())) {
            ReceivingAddrInfo addrInfo = addrInfoMapper.getByReceivingAddrId(buyDto.getReceivingAddrId());
            order.setReceiverAddrId(buyDto.getReceivingAddrId());
            order.setReceiverAddress(addrInfo.getReceivingAddress());
            order.setReceiverMobile(addrInfo.getContactPhone());
            order.setReceiver(addrInfo.getContact());
        }
        order.setUserId(userId);
        order.setBuyerNick(user.getNickName());
        order.setPayType(buyDto.getPayType());
        order.setActualPay(totalPay);
        order.setTotalMoney(totalMoney);
        order.setPayStatus(PayStatus.PAYING.value());
        order.setDiscountStr(discountStr);
        order.setDiscountMoney(discountMoney);
        order.setRemark(buyDto.getRemark());
        order.setCouponRecordId(buyDto.getCouponRecordId());
        order.setCommission(buyDto.getCommission());
        List<MyShopCart> carts = new ArrayList<>();
        if (CollectionUtil.isEmpty(buyDto.getCartIds())){//默认购物车所有
            carts = shoppingCartMapper.myCart(userId);
        }else{
            carts = shoppingCartMapper.getSkuByCartIds(buyDto.getCartIds());
        }
        List<ShoppingOrderDetail> orderDetails = new ArrayList<>();
        Double totalPointPay =  0d;
        for (MyShopCart cart:carts) {
            //订单详情
            ShoppingOrderDetail detail = new ShoppingOrderDetail();
            detail.setOrderNo(orderNo);
            detail.setSpuId(cart.getSpuId());
            detail.setProductName(cart.getProductName());
            detail.setSkuId(cart.getSkuId());
            detail.setSkuName(cart.getSkuName());
            detail.setSkuSpecs(cart.getSkuSpecs());
            detail.setImage(cart.getSkuImgUrl());
            BigDecimal price = BigDecimalUtil.mul(null != cart.getDiscountPrice() ? cart.getDiscountPrice() : cart.getOrginPrice(),cart.getNumCount());
            if (null!=discountType&&discountType==1){
                detail.setPrice(price.multiply(new BigDecimal(discount)).doubleValue());
                detail.setTotalMoney(price.doubleValue());
            }else {
                detail.setPrice(price.doubleValue());
                detail.setTotalMoney(price.doubleValue());
            }
            detail.setNumCount(cart.getNumCount());
            orderDetails.add(detail);
            if (!buyDto.getCartIds().contains(cart.getCartId())) {
                buyDto.getCartIds().add(cart.getCartId());
            }
            totalPointPay = totalPointPay+(null!=cart.getRequirePoint()?cart.getRequirePoint():0);
        }

        shoppingCartMapper.setOrderNo(orderNo,buyDto.getCartIds());

        if (totalPay==0) {
            //主动触发回调
            for (ShoppingOrderDetail detail : orderDetails) {
                detail.setStatus(ShoppingStatus.SUCCESS.value());
            }
            order.setPayTime(new Date());
            order.setCloseTime(new Date());
            order.setEndTime(new Date());
            order.setPayStatus(PayStatus.SUCCESS.value());
            for (MyShopCart detail : carts) {
                ShoppingSku dbSku = shoppingSkuMapper.getBySkuId(detail.getSkuId());
                String key = "sku_" + detail.getSkuId();
                //实物产品修改产品库存数
                String lock_key = "sku_lock_" + detail.getSkuId();
                RLock lock = redisson.getLock(lock_key);
                //try catch 设计是为了防止在执行业务的时候出现异常导致redis锁一直无法释放
                try {
                    lock.lock();
                    int count = Integer.parseInt(redisUtil.get(key).toString());
                    int stockCount = count - detail.getNumCount();
                    if (dbSku.getLockStockCount() >= stockCount || 0 >= stockCount) {
                        dbSku.setSaleStatus(SaleStatus.SELL_OUT.value());
                    }
                    int saleCount = dbSku.getSaleStockCount() + detail.getNumCount();
                    dbSku.setSaleStockCount(saleCount);
                    redisUtil.set(key, stockCount);
                    dbSku.setStockCount(stockCount);
                    shoppingSkuMapper.updateStockCount(dbSku);
                } catch (Throwable e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
            for (String cartId : buyDto.getCartIds()) {
                shoppingCartMapper.deleteById(cartId);
            }
            //如果存在优惠券，修改为已使用
            if (StringUtils.isNotEmpty(buyDto.getCouponRecordId())) {
                UserCouponRecord record = couponRecordMapper.getByCouponRecordId(buyDto.getCouponRecordId());
                if (null != record.getIsForever() && record.getIsForever() != 1) {
                    couponRecordMapper.updateStatus(buyDto.getCouponRecordId(), 1);
                }
            }
            shoppingOrderDetailMapper.insertBatch(orderDetails);
            shoppingOrderMapper.initOrder(order);
            WxOrderResult wxOrder = new WxOrderResult();
            wxOrder.setOrderNo(orderNo);
            return new HttpResult(wxOrder);
        }

        // TODO 调用统一生成订单接口
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setSignType(WxPayConstants.SignType.MD5);
        orderRequest.setBody("商城购买");
        orderRequest.setOutTradeNo(orderNo); //自己生成order_No
        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(order.getActualPay().toString()));//直接分
        orderRequest.setOpenid(userId); // 获取微信支付用户的openId
        orderRequest.setSpbillCreateIp(IpUtil.getRealIp(request));
        Date now = new Date();
        Date afterDate = DateUtils.add(now, Calendar.MINUTE, 10);//10分钟后
        orderRequest.setTimeStart(DateUtils.format(now, DateUtils.yyyyMMddHHmmssFormat));
        orderRequest.setTimeExpire(DateUtils.format(afterDate, DateUtils.yyyyMMddHHmmssFormat));
        orderRequest.setNotifyUrl(shoppingNotifyUrl);

        WxPayMpOrderResult wxPayMpOrderResult = wxService.createOrder(orderRequest);
        log.info("微信支付下单返回："+wxPayMpOrderResult.toString());
        WxOrderResult wxOrder = new WxOrderResult();
        wxOrder.setWxPayMpOrderResult(wxPayMpOrderResult);
        wxOrder.setOrderNo(orderNo);
        //如果存在优惠券，修改为已使用
        if (StringUtils.isNotEmpty(buyDto.getCouponRecordId())){
            UserCouponRecord record = couponRecordMapper.getByCouponRecordId(buyDto.getCouponRecordId());
            if (record.getIsForever()!=1) {
                couponRecordMapper.updateStatus(buyDto.getCouponRecordId(), 1);
            }
        }
        shoppingOrderDetailMapper.insertBatch(orderDetails);
        shoppingOrderMapper.initOrder(order);
        return new HttpResult(wxOrder);
    }


    @Override
    public HttpResult shoppingTrade(HttpServletRequest request, ComposeCommitDto qto) {
        Map resultMap = new HashMap();
        BigDecimal totalMoney = new BigDecimal("0");
        BigDecimal totalPay = new BigDecimal("0");
        String discountStr = "";
        String discountFrom = "";
        String userId = tokenUtil.getUserId(request);
        ShoppingSku cart = shoppingSkuMapper.getBySkuId(qto.getSkuId());
        if (null==cart||cart.getSaleStatus()!=SaleStatus.LISTING.value()){
            return HttpResult.fail("该商品已下架！");
        }
        cart.setNumCount(qto.getNumCount());
        //先获取用户，判断用户会员等级
        UserInfo user = userMapper.getByUserId(userId);
        //使用优惠券特别折扣
        if (StringUtils.isNotEmpty(qto.getCouponRecordId())){
            //校验折扣券是否可用，防止爬虫通过过期券调用
            UserCouponRecord couponRecord = couponRecordMapper.getByCouponRecordId(qto.getCouponRecordId());
//            if (couponRecord.getStatus()!=0){
//                return HttpResult.fail("该券已经使用或已失效！");
//            }
            if (couponRecord.getUseWay()==1){
                return HttpResult.fail("该券不是车检优惠券！");
            }

            Integer couponWay = couponRecord.getCouponWay();
            BigDecimal discount = new BigDecimal(new Double(couponRecord.getDiscount()).toString());
            BigDecimal price = BigDecimalUtil.mul(null != cart.getDiscountPrice() ? cart.getDiscountPrice() : cart.getOrginPrice(),cart.getNumCount());
            totalMoney = totalMoney.add(price);
            if (couponWay==1){//折扣券
                discount = new BigDecimal(new Double(couponRecord.getDiscount()).toString());
                discountStr = "享折扣券"+discount.doubleValue()*10+"折优惠";
                discountFrom = "折扣券优惠";
                totalPay = totalPay.add(totalMoney.multiply(discount));
                resultMap.put("discount",NumberUtils.numFormat(discount.doubleValue()));
                resultMap.put("discountType",1);
            }else if (couponWay==2){//现金券
                totalPay = totalPay.add(totalMoney.subtract(discount));
                discountStr = "享现金券"+discount.doubleValue()+"元优惠";
                discountFrom = "现金券优惠";
                resultMap.put("discountType",2);
            }else{//满减券
                //最低金额是否达到
                if(totalMoney.doubleValue()<couponRecord.getLowerMoney()){
                    return HttpResult.fail("未达到满减券最低消费金额！");
                }
                totalPay = totalPay.add(totalMoney.subtract(discount));
                discountStr = "享现金券"+discount.doubleValue()+"元优惠";
                discountFrom = "现金券优惠";
                resultMap.put("discountType",2);
            }
        }else{//按照原价计算
            BigDecimal price = BigDecimalUtil.mul(null != cart.getDiscountPrice() ? cart.getDiscountPrice() : cart.getOrginPrice(),cart.getNumCount());
            totalMoney = totalMoney.add(price);
            totalPay = totalPay.add(price);
        }

        //佣金
        if (null!=qto.getCommission()) {
            if (null==user.getBalance()||user.getBalance()< qto.getCommission()){
                return HttpResult.fail("佣金余额不足！！");
            }
            BigDecimal commission = new BigDecimal(qto.getCommission());
            totalPay = totalPay.subtract(commission);
            resultMap.put("commission",NumberUtils.numFormat(commission));
        }

        if (StringUtils.isNotEmpty(discountStr)) {
            Double discountMoney = totalMoney.subtract(totalPay).doubleValue();
            resultMap.put("discountMoney",NumberUtils.numFormat(discountMoney));
            resultMap.put("discountStr",discountStr);
            resultMap.put("discountFrom",discountFrom);
        }

        resultMap.put("totalMoney",NumberUtils.numFormat(totalMoney.doubleValue()));
        resultMap.put("totalPay",NumberUtils.numFormat(totalPay.doubleValue()));
        return new HttpResult(resultMap);
    }


    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public HttpResult shoppingOrder(HttpServletRequest request, ComposeCommitDto buyDto) throws WxPayException {
        ShoppingSku cart = shoppingSkuMapper.getBySkuId(buyDto.getSkuId());
        if (null==cart||cart.getSaleStatus()!=SaleStatus.LISTING.value()){
            return HttpResult.fail("该商品已下架！");
        }
        String userId = tokenUtil.getUserId(request);
        UserInfo user = userMapper.getByUserId(userId);
        HttpResult httpResult = this.shoppingTrade(request, buyDto);
        Map resultMap = (Map)httpResult.getData();
        String discountStr = null!=resultMap.get("discountStr")?resultMap.get("discountStr").toString():"";
        Double discountMoney = null!=resultMap.get("discountMoney")?Double.valueOf(resultMap.get("discountMoney").toString()):null;
        Double totalMoney = null!=resultMap.get("totalMoney")?Double.valueOf(resultMap.get("totalMoney").toString()):null;
        Double totalPay = null!=resultMap.get("totalPay")?Double.valueOf(resultMap.get("totalPay").toString()):null;
        Double discount = null!=resultMap.get("discount")?Double.valueOf(resultMap.get("discount").toString()):null;
        Integer discountType = null!=resultMap.get("discountType")?Integer.valueOf(resultMap.get("discountType").toString()):null;
        if (totalPay<0){
            return HttpResult.fail("您还未添加购物车，请确认！");
        }
        //创建订单号
        String code = CodeUtil.verifyCode(6);
        String today = DateUtil.format(new Date(), "yyyyMMdd");
        String orderNo = "so".concat(today).concat(code);

        ShoppingOrder order = new ShoppingOrder();
        order.setOrderNo(orderNo);
        if (StringUtils.isNotEmpty(buyDto.getReceivingAddrId())) {
            ReceivingAddrInfo addrInfo = addrInfoMapper.getByReceivingAddrId(buyDto.getReceivingAddrId());
            order.setReceiverAddrId(buyDto.getReceivingAddrId());
            order.setReceiverAddress(addrInfo.getReceivingAddress());
            order.setReceiverMobile(addrInfo.getContactPhone());
            order.setReceiver(addrInfo.getContact());
        }
        order.setUserId(userId);
        order.setBuyerNick(user.getNickName());
        order.setPayType(buyDto.getPayType());
        order.setActualPay(totalPay);
        order.setTotalMoney(totalMoney);
        order.setPayStatus(PayStatus.PAYING.value());
        order.setDiscountStr(discountStr);
        order.setDiscountMoney(discountMoney);
        order.setRemark(buyDto.getRemark());
        order.setCouponRecordId(buyDto.getCouponRecordId());
        order.setCommission(buyDto.getCommission());

        cart.setNumCount(buyDto.getNumCount());
        ShoppingOrderDetail detail = new ShoppingOrderDetail();
        detail.setOrderNo(orderNo);
        detail.setSpuId(cart.getSpuId());
        detail.setProductName(cart.getProductName());
        detail.setSkuId(cart.getSkuId());
        detail.setSkuName(cart.getSkuName());
        detail.setSkuSpecs(cart.getSkuSpecs());
        detail.setImage(cart.getSkuImgUrl());
        BigDecimal price = BigDecimalUtil.mul(null != cart.getDiscountPrice() ? cart.getDiscountPrice() : cart.getOrginPrice(),cart.getNumCount());
        detail.setTotalMoney(price.doubleValue());
        if (null!=discountType&&discountType==1){
            detail.setPrice(price.multiply(new BigDecimal(discount)).doubleValue());
        }else{
            detail.setPrice(price.doubleValue());
        }
        detail.setNumCount(cart.getNumCount());

        //如果存在优惠券，修改为已使用
        if (StringUtils.isNotEmpty(buyDto.getCouponRecordId())){
            UserCouponRecord record = couponRecordMapper.getByCouponRecordId(buyDto.getCouponRecordId());
            if (null!=record.getIsForever()&&record.getIsForever()!=1) {
                couponRecordMapper.updateStatus(buyDto.getCouponRecordId(), 1);
            }
        }

        if (totalPay==0) {
            //主动触发回调
            detail.setStatus(ShoppingStatus.SUCCESS.value());
            order.setPayTime(new Date());
            order.setCloseTime(new Date());
            order.setEndTime(new Date());
            order.setPayStatus(PayStatus.SUCCESS.value());
            ShoppingSku dbSku = shoppingSkuMapper.getBySkuId(cart.getSkuId());
            String key = "sku_" + cart.getSkuId();
            //实物产品修改产品库存数
            String lock_key = "sku_lock_" + cart.getSkuId();
            RLock lock = redisson.getLock(lock_key);
            //try catch 设计是为了防止在执行业务的时候出现异常导致redis锁一直无法释放
            try {
                lock.lock();
                int count = Integer.parseInt(redisUtil.get(key).toString());
                int stockCount = count - cart.getNumCount();
                if (dbSku.getLockStockCount() >= stockCount || 0 >= stockCount) {
                    dbSku.setSaleStatus(SaleStatus.SELL_OUT.value());
                }
                int saleCount = dbSku.getSaleStockCount() + cart.getNumCount();
                dbSku.setSaleStockCount(saleCount);
                redisUtil.set(key, stockCount);
                dbSku.setStockCount(stockCount);
                shoppingSkuMapper.updateStockCount(dbSku);
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            shoppingOrderDetailMapper.insert(detail);
            shoppingOrderMapper.initOrder(order);
            WxOrderResult wxOrder = new WxOrderResult();
            wxOrder.setOrderNo(orderNo);
            return new HttpResult(wxOrder);
        }

        // TODO 调用统一生成订单接口
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setSignType(WxPayConstants.SignType.MD5);
        orderRequest.setBody("商城购买");
        orderRequest.setOutTradeNo(orderNo); //自己生成order_No
        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
        orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(order.getActualPay().toString()));//直接分
        orderRequest.setOpenid(userId); // 获取微信支付用户的openId
        orderRequest.setSpbillCreateIp(IpUtil.getRealIp(request));
        Date now = new Date();
        Date afterDate = DateUtils.add(now, Calendar.MINUTE, 10);//10分钟后
        orderRequest.setTimeStart(DateUtils.format(now, DateUtils.yyyyMMddHHmmssFormat));
        orderRequest.setTimeExpire(DateUtils.format(afterDate, DateUtils.yyyyMMddHHmmssFormat));
        orderRequest.setNotifyUrl(shoppingNotifyUrl);

        shoppingOrderDetailMapper.insert(detail);
        shoppingOrderMapper.initOrder(order);
        WxPayMpOrderResult wxPayMpOrderResult = wxService.createOrder(orderRequest);
        log.info("微信支付下单返回："+wxPayMpOrderResult.toString());
        WxOrderResult wxOrder = new WxOrderResult();
        wxOrder.setWxPayMpOrderResult(wxPayMpOrderResult);
        wxOrder.setOrderNo(orderNo);
        return new HttpResult(wxOrder);
    }



    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @Override
    public String shoppingNotify(HttpServletRequest request, Boolean isCart) {
        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayOrderNotifyResult notifyResult = wxService.parseOrderNotifyResult(xmlResult);
            String orderNo = notifyResult.getOutTradeNo();
            String tradeNo = notifyResult.getTransactionId();
            String totalFee = BaseWxPayResult.fenToYuan(notifyResult.getTotalFee());

//            shoppingOrderMapper.setSign(orderNo,payResult.getSign());
            ShoppingOrder order = shoppingOrderMapper.getByOrderNo(orderNo);
            if(order.getPayStatus()!=PayStatus.PAYING.value()){
                log.info("电商订单号："+orderNo+"，微信支付重复回调");
                return WxPayNotifyResponse.success("success");
            }
            order.setPayTime(new Date());
            order.setCloseTime(new Date());
            order.setEndTime(new Date());
            if(!"SUCCESS".equals(notifyResult.getResultCode())) {
                order.setPayStatus(PayStatus.FAIL.value());
//                order.setFailReason(notifyResult.get());
                shoppingOrderMapper.updateOrder(order);
                return WxPayNotifyResponse.success("success");
            }
            if (Double.valueOf(totalFee)<order.getActualPay()){
                order.setPayStatus(PayStatus.FAIL.value());
                order.setFailReason("订单金额应该与返回金额不一致");
                shoppingOrderMapper.updateOrder(order);
                return WxPayNotifyResponse.fail("订单金额应该与返回金额不一致");
            }
            order.setPayStatus(PayStatus.SUCCESS.value());

            List<ShoppingOrderDetail> orderDetails = shoppingOrderDetailMapper.getByOrderNo(orderNo);
            if (!CollectionUtils.isEmpty(orderDetails)){
                for (ShoppingOrderDetail detail :orderDetails) {
                    ShoppingSku dbSku = shoppingSkuMapper.getBySkuId(detail.getSkuId());
                    String key="sku_" + detail.getSkuId();
                    //实物产品修改产品库存数
                    String lock_key="sku_lock_"+detail.getSkuId();
                    RLock lock = redisson.getLock(lock_key);
                    //try catch 设计是为了防止在执行业务的时候出现异常导致redis锁一直无法释放
                    try {
                        lock.lock();
                        int count = Integer.parseInt(redisUtil.get(key).toString());
                        int stockCount = count-detail.getNumCount();
                        if (dbSku.getLockStockCount()>=stockCount||0>=stockCount){
                            dbSku.setSaleStatus(SaleStatus.SELL_OUT.value());
                        }
                        int saleCount = dbSku.getSaleStockCount()+detail.getNumCount();
                        dbSku.setSaleStockCount(saleCount);
                        redisUtil.set(key, stockCount);
                        dbSku.setStockCount(stockCount);
                        shoppingSkuMapper.updateStockCount(dbSku);
                    } catch (Throwable e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
//                    shoppingOrderMapper.confirmOrder(orderNo, detail.getSkuId(), 1);
                    //修改状态
                    detail.setStatus(ShoppingStatus.SUCCESS.value());
                    shoppingOrderDetailMapper.updateStatus(detail);
                }
            }
            if (isCart){//清空购物车
                shoppingCartMapper.deleteByOrderNo(orderNo);
            }
            shoppingOrderMapper.updateOrder(order);
            //扣除佣金
            UserInfo user = userMapper.getByUserId(order.getUserId());
            if (null!=order.getCommission()) {
                BigDecimal num1 = new BigDecimal(new Double(user.getBalance()).toString());
                BigDecimal num2 = new BigDecimal(new Double(order.getCommission()).toString());
                user.setBalance(num1.subtract(num2).doubleValue());
                userMapper.updateBalance(user);
                UserBalanceRecord balanceRecord = new UserBalanceRecord();
                balanceRecord.setBalance(order.getCommission());
                balanceRecord.setUserId(user.getUserId());
                balanceRecord.setRecordName("商城扣减佣金");
                balanceRecord.setRecordType(2);
                balanceRecord.setOrderNo(order.getOrderNo());
                balanceRecordMapper.insert(balanceRecord);
            }
            //消息
            UserMessage message = new UserMessage();
            message.setMsgType(3);
            message.setOrderNo(orderNo);
            message.setContent("您已下单成功，请等待商家发货！");
            message.setUserId(order.getUserId());
            userMessageMapper.insert(message);

            return WxPayNotifyResponse.success("success");
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException("产品购买回调失败"+e.getMessage());
        }
    }


    @Override
    public String backShoppingNotify(HttpServletRequest request) {

        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayRefundNotifyResult notifyResult = wxService.parseRefundNotifyResult(xmlResult);
            //判断你返回状态信息是否正确
            if ("SUCCESS".equals(notifyResult.getReturnCode())) {
                WxPayRefundNotifyResult.ReqInfo reqInfo = notifyResult.getReqInfo();
                //判断退款状态
                if ("SUCCESS".equals(reqInfo.getRefundStatus())) {
                    //内部订单号
                    String orderNo = reqInfo.getOutTradeNo();
                    String refundNo = reqInfo.getOutRefundNo();
                    ShoppingRefundOrder refundOrder = shoppingRefundOrderMapper.getByRefundNo(refundNo);
                    if (refundOrder.getRefundStatus()==RefundStatus.SUCCESS.value()){
                        return WxPayNotifyResponse.success("success");
                    }
                    refundOrder.setRefundStatus(RefundStatus.SUCCESS.value());
                    refundOrder.setSettlementRefundFee(reqInfo.getSettlementRefundFee());
                    refundOrder.setRefundTime(new Date());
                    shoppingRefundOrderMapper.update(refundOrder);
                    //如果存在优惠券
                    if (StringUtils.isNotEmpty(refundOrder.getCouponRecordId())){
                        couponRecordMapper.updateStatus(refundOrder.getCouponRecordId(), 0);
                    }
                    //如果存在佣金
                    if (null!=refundOrder.getCommission()) {
                        UserInfo user = userMapper.getByUserId(refundOrder.getUserId());
                        BigDecimal num1 = new BigDecimal(new Double(user.getBalance()).toString());
                        BigDecimal num2 = new BigDecimal(new Double(refundOrder.getCommission()).toString());
                        user.setBalance(num1.add(num2).doubleValue());
                        userMapper.updateBalance(user);

                        UserBalanceRecord balanceRecord = new UserBalanceRecord();
                        balanceRecord.setBalance(refundOrder.getCommission());
                        balanceRecord.setUserId(user.getUserId());
                        balanceRecord.setRecordName("商城退还佣金");
                        balanceRecord.setRecordType(1);
                        balanceRecord.setOrderNo(orderNo);
                        balanceRecordMapper.insert(balanceRecord);
                    }
                    ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(orderNo, refundOrder.getSkuId());
                    detail.setStatus(ShoppingStatus.REFUND_SUCCESS.value());
                    shoppingOrderDetailMapper.updateStatus(detail);
                    //消息
                    UserMessage message = new UserMessage();
                    message.setMsgType(3);
                    message.setOrderNo(orderNo);
                    message.setContent("您已退单成功！");
                    message.setUserId(refundOrder.getUserId());
                    userMessageMapper.insert(message);
                    return WxPayNotifyResponse.success("success");
                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return WxPayNotifyResponse.fail("回调异常");
    }

    @Override
    public void successPay(String orderNo,Integer totalFee,String tradeState) {
        try {
            ShoppingOrder order = shoppingOrderMapper.getByOrderNo(orderNo);
            if(!"SUCCESS".equals(tradeState)) {
                order.setPayStatus(PayStatus.FAIL.value());
                shoppingOrderMapper.updateOrder(order);
                return;
            }
            order.setPayTime(new Date());
            order.setCloseTime(new Date());
            order.setEndTime(new Date());
            Integer actualPay = BaseWxPayRequest.yuanToFen(order.getActualPay().toString());
            if (totalFee<actualPay){
                order.setPayStatus(PayStatus.FAIL.value());
                order.setFailReason("订单金额应该与返回金额不一致");
                shoppingOrderMapper.updateOrder(order);
                return;
            }
            order.setPayStatus(PayStatus.SUCCESS.value());
            List<ShoppingOrderDetail> orderDetails = shoppingOrderDetailMapper.getByOrderNo(orderNo);
            if (!CollectionUtils.isEmpty(orderDetails)){
                for (ShoppingOrderDetail detail :orderDetails) {
                    ShoppingSku dbSku = shoppingSkuMapper.getBySkuId(detail.getSkuId());
                    String key="sku_" + detail.getSkuId();
                    //实物产品修改产品库存数
                    String lock_key="sku_lock_"+detail.getSkuId();
                    RLock lock = redisson.getLock(lock_key);
                    //try catch 设计是为了防止在执行业务的时候出现异常导致redis锁一直无法释放
                    try {
                        lock.lock();
                        int count = Integer.parseInt(redisUtil.get(key).toString());
                        int stockCount = count-detail.getNumCount();
                        if (dbSku.getLockStockCount()>=stockCount||0>=stockCount){
                            dbSku.setSaleStatus(SaleStatus.SELL_OUT.value());
                        }
                        int saleCount = dbSku.getSaleStockCount()+detail.getNumCount();
                        dbSku.setSaleStockCount(saleCount);
                        redisUtil.set(key, stockCount);
                        dbSku.setStockCount(stockCount);
                        shoppingSkuMapper.updateStockCount(dbSku);
                    } catch (Throwable e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
//                    shoppingOrderMapper.confirmOrder(orderNo, detail.getSkuId(), 1);
                    //修改状态
                    detail.setStatus(ShoppingStatus.SUCCESS.value());
                    shoppingOrderDetailMapper.updateStatus(detail);
                }
            }
            shoppingCartMapper.deleteByOrderNo(orderNo);
            //更新积分赠送记录的状态为有效
            pointRecordMapper.updateStatus(orderNo,1);
            shoppingOrderMapper.updateOrder(order);
            //累积消费
            UserInfo user = userMapper.getByUserId(order.getUserId());
            BigDecimal num1 = new BigDecimal(new Double(user.getAccrueExpend()).toString());
            BigDecimal num2 = new BigDecimal(new Double(order.getActualPay()).toString());
            user.setAccrueExpend(num1.add(num2).doubleValue());
            userMapper.updateAccrueExpend(user);
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException("产品购买回调失败"+e.getMessage());
        }
    }

    @Override
    public HttpResult refundProduct(HttpServletRequest request, ComposeCommitDto qto) {
        try {
            ShoppingRefundOrder dbRefundOrder =refundOrderMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
            if (null!=dbRefundOrder){
                return HttpResult.fail("该订单已存在退单，继续退款请联系客服！");
            }
            ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(qto.getOrderNo(),qto.getSkuId());

            if (detail.getStatus()==ShoppingStatus.TRANSPORT.value()) {
                if (StringUtils.isEmpty(qto.getImgUrls())) {
                    return HttpResult.fail("请上传图片凭证！");
                }
                if (StringUtils.isEmpty(qto.getRefundReason())) {
                    return HttpResult.fail("请填写退货原因！");
                }
            }
            String userId = tokenUtil.getUserId(request);
            //通过订单号查询商品id
            ShoppingOrder order = shoppingOrderMapper.getByOrderNo(qto.getOrderNo());
            //订单总金额
            Integer longValueOrderAmount = BaseWxPayRequest.yuanToFen(order.getActualPay().toString());
            //退款金额
            Integer longValueRefundAmount = BaseWxPayRequest.yuanToFen(detail.getPrice().toString());
            //创建退款订单号
            String code = CodeUtil.verifyCode(6);
            String today = DateUtil.format(new Date(), "yyyyMMdd");
            String refundNo = "re".concat(today).concat(code);

            ShoppingRefundOrder refundOrder = new ShoppingRefundOrder();
            refundOrder.setRefundNo(refundNo);
            refundOrder.setRefundFee(longValueRefundAmount);
            refundOrder.setTotalFee(longValueOrderAmount);
            refundOrder.setTotalPoint(detail.getTotalPoint());
            refundOrder.setOrderNo(qto.getOrderNo());
            refundOrder.setUserId(userId);
            refundOrder.setSkuId(qto.getSkuId());
            refundOrder.setRefundReason(qto.getRefundReason());
            refundOrder.setImgUrls(qto.getImgUrls());
            refundOrder.setCommission(order.getCommission());
            refundOrder.setCouponRecordId(order.getCouponRecordId());
            refundOrderMapper.insert(refundOrder);

            if (detail.getStatus()==ShoppingStatus.SUCCESS.value()) {
                if(longValueOrderAmount==0){//全部是佣金支付的
                    refundOrder.setRefundStatus(RefundStatus.SUCCESS.value());
                    refundOrder.setSettlementRefundFee(longValueRefundAmount);
                    refundOrder.setRefundTime(new Date());
                    shoppingRefundOrderMapper.update(refundOrder);
                    //如果存在优惠券
                    if (StringUtils.isNotEmpty(refundOrder.getCouponRecordId())){
                        couponRecordMapper.updateStatus(refundOrder.getCouponRecordId(), 0);
                    }
                    //如果存在佣金
                    if (null!=refundOrder.getCommission()) {
                        UserInfo user = userMapper.getByUserId(refundOrder.getUserId());
                        BigDecimal num1 = new BigDecimal(new Double(user.getBalance()).toString());
                        BigDecimal num2 = new BigDecimal(new Double(refundOrder.getCommission()).toString());
                        user.setBalance(num1.add(num2).doubleValue());
                        userMapper.updateBalance(user);

                        UserBalanceRecord balanceRecord = new UserBalanceRecord();
                        balanceRecord.setBalance(refundOrder.getCommission());
                        balanceRecord.setUserId(user.getUserId());
                        balanceRecord.setRecordName("商城退还佣金");
                        balanceRecord.setRecordType(1);
                        balanceRecord.setOrderNo(order.getOrderNo());
                        balanceRecordMapper.insert(balanceRecord);
                    }
                    detail.setStatus(ShoppingStatus.REFUND_SUCCESS.value());
                    shoppingOrderDetailMapper.updateStatus(detail);
                    //消息
                    UserMessage message = new UserMessage();
                    message.setMsgType(3);
                    message.setOrderNo(order.getOrderNo());
                    message.setContent("您已退单成功！");
                    message.setUserId(refundOrder.getUserId());
                    userMessageMapper.insert(message);
                    return HttpResult.OK;
                }
                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
                refundRequest.setOutTradeNo(refundOrder.getOrderNo());
                refundRequest.setOutRefundNo(refundNo);
                refundRequest.setTotalFee(refundOrder.getTotalFee());
                refundRequest.setRefundFee(longValueRefundAmount);
                refundRequest.setNotifyUrl(backShoppingNotifyUrl);
                try {
                    WxPayRefundResult refund = wxService.refund(refundRequest);
                    log.info("退款返回：{}", refund);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                refundOrder.setRefundStatus(RefundStatus.REFUNDING.value());
                shoppingRefundOrderMapper.update(refundOrder);
                return HttpResult.OK;
            }else{
                if (StringUtils.isEmpty(qto.getImgUrls())){
                    return HttpResult.fail("请上传图片凭证！");
                }
                if (StringUtils.isEmpty(qto.getRefundReason())){
                    return HttpResult.fail("请填写退货原因！");
                }
            }
            //修改子订单状态
            int statusBeforeRefund = detail.getStatus();
            detail.setStatusBeforeRefund(statusBeforeRefund);
            shoppingOrderDetailMapper.updateBeforeStatus(detail);
            detail.setStatus(ShoppingStatus.REFUND.value());
            shoppingOrderDetailMapper.updateStatus(detail);
            //消息
            UserMessage message = new UserMessage();
            message.setMsgType(3);
            message.setOrderNo(qto.getOrderNo());
            message.setContent("您的退单申请已发送，请等待商家审核！");
            message.setUserId(userId);
            userMessageMapper.insert(message);
            return HttpResult.OK;
        }catch (Exception e){
            e.printStackTrace();
            return HttpResult.fail("退款失败");
        }
    }


    @Override
    public HttpResult changeProduct(HttpServletRequest request, ComposeCommitDto qto) {
        try {
            //通过订单号查询商品id
            ShoppingOrder order = shoppingOrderMapper.getByOrderNo(qto.getOrderNo());
            ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
            if (null!=detail&&detail.getStatus()==ShoppingStatus.CHANGE.value()){
                return HttpResult.fail("该订单已存在换单，继续换货请联系客服！");
            }
            ShoppingSku newSku = shoppingSkuMapper.getBySkuId(qto.getNewSkuId());
            if (newSku.getOrginPrice()!=newSku.getOrginPrice()){
                return HttpResult.fail("价格不一致，暂不支持换货，请退货后重新购买！");
            }
            //创建订单号
            String code = CodeUtil.verifyCode(6);
            String today = DateUtil.format(new Date(), "yyyyMMdd");
            String changeNo = "CH".concat(today).concat(code);

            ShoppingChangeOrder changeOrder = new ShoppingChangeOrder();
            changeOrder.setOrderNo(qto.getOrderNo());
            changeOrder.setChangeNo(changeNo);
            if (StringUtils.isNotEmpty(qto.getReceivingAddrId())) {
                ReceivingAddrInfo addrInfo = addrInfoMapper.getByReceivingAddrId(qto.getReceivingAddrId());
                changeOrder.setReceiverAddrId(qto.getReceivingAddrId());
                changeOrder.setReceiverAddress(addrInfo.getReceivingAddress());
                changeOrder.setReceiverMobile(addrInfo.getContactPhone());
                changeOrder.setReceiver(addrInfo.getContact());
            }
            changeOrder.setUserId(order.getUserId());
            changeOrder.setSkuId(qto.getSkuId());
            changeOrder.setChangeStatus(ChangeStatus.INIT.value());
            changeOrder.setNewSkuId(qto.getNewSkuId());
            changeOrder.setChangeReason(qto.getChangeReason());
            changeOrder.setRemark(qto.getRemark());
            changeOrder.setReturnedShippingName(qto.getShippingName());
            changeOrder.setReturnedShippingNameCode(qto.getShippingNameCode());
            changeOrder.setReturnedShippingCode(qto.getShippingCode());
            changeOrderMapper.insert(changeOrder);
            //修改子订单状态
            int statusBeforeRefund = detail.getStatus();
            detail.setStatusBeforeRefund(statusBeforeRefund);
            shoppingOrderDetailMapper.updateBeforeStatus(detail);
            detail.setStatus(ShoppingStatus.CHANGE.value());
            shoppingOrderDetailMapper.updateStatus(detail);
            //消息
            UserMessage message = new UserMessage();
            message.setMsgType(3);
            message.setOrderNo(qto.getOrderNo());
            message.setContent("您的换货申请已发送，请等待商家审核！");
            message.setUserId(order.getUserId());
            userMessageMapper.insert(message);
            return HttpResult.OK;
        }catch (Exception e){
            e.printStackTrace();
            return HttpResult.fail("换货失败");
        }
    }


    @Override
    public HttpResult changeDetail(HttpServletRequest request, ComposeCommitDto qto) {
        ShoppingChangeOrder changeOrder =changeOrderMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
        changeOrder.setSku(shoppingSkuMapper.getBySkuId(changeOrder.getSkuId()));
        changeOrder.setNewSku(shoppingSkuMapper.getBySkuId(changeOrder.getNewSkuId()));
        return new HttpResult(changeOrder);
    }

    @Override
    public HttpResult cancelChange(HttpServletRequest request, ComposeCommitDto qto) {
        ShoppingChangeOrder changeOrder =changeOrderMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
        changeOrderMapper.deleteByPrimaryKey(changeOrder.getChangeNo());
        //通过订单号查询商品id
        ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
        //修改订单状态
        detail.setStatus(detail.getStatusBeforeRefund());
        shoppingOrderDetailMapper.updateStatus(detail);
        //消息
        UserMessage message = new UserMessage();
        message.setMsgType(3);
        message.setOrderNo(qto.getOrderNo());
        message.setContent("您的换货申请已取消！");
        message.setUserId(changeOrder.getUserId());
        userMessageMapper.insert(message);
        return HttpResult.OK;
    }


//    @Override
//    public HttpResult fillChangeInfo(HttpServletRequest request, ComposeQueryDto qto) {
//        ShoppingChangeOrder changeOrder =changeOrderMapper.getByChangeNo(qto.getChangeNo());
//        if (null==changeOrder){
//            return HttpResult.fail("未查询到相关换货记录！");
//        }
//        if (changeOrder.getChangeStatus()!= ChangeStatus.ACCEPTED.value()){
//            return HttpResult.fail("请等待商家处理！");
//        }
//        changeOrder.setReturnedShippingCode(qto.getShippingCode());
//        changeOrder.setReturnedShippingName(qto.getShippingName());
//        changeOrder.setChangeStatus(RefundStatus.RETURNED.value());
//        changeOrderMapper.update(changeOrder);
//        return HttpResult.OK;
//    }


    @Override
    public HttpResult cancelRefund(HttpServletRequest request, ComposeCommitDto qto) {
        ShoppingRefundOrder dbRefundOrder =refundOrderMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
//        dbRefundOrder.setRefundStatus(RefundStatus.CANCEL.value());
//        refundOrderMapper.update(dbRefundOrder);
        refundOrderMapper.deleteByPrimaryKey(dbRefundOrder.getRefundNo());
        //通过订单号查询商品id
        ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(qto.getOrderNo(),qto.getSkuId());
        //修改订单状态
        detail.setStatus(detail.getStatusBeforeRefund());
        shoppingOrderDetailMapper.updateStatus(detail);

        //消息
        UserMessage message = new UserMessage();
        message.setMsgType(3);
        message.setOrderNo(qto.getOrderNo());
        message.setContent("您的退款申请已取消！");
        message.setUserId(dbRefundOrder.getUserId());
        userMessageMapper.insert(message);
        return HttpResult.OK;
    }


    @Override
    public HttpResult fillReturnInfo(HttpServletRequest request, ComposeQueryDto qto) {
        ShoppingRefundOrder refundOrder = refundOrderMapper.getDetail(qto.getOrderNo(), qto.getSkuId());
        refundOrder.setShippingCode(qto.getShippingCode());
        refundOrder.setShippingName(qto.getShippingName());
        refundOrder.setRefundStatus(RefundStatus.RETURNED.value());
        refundOrderMapper.update(refundOrder);
        return HttpResult.OK;
    }



    @Override
    public HttpResult logistics(ComposeQueryDto queryDto) {
        ObjectMapper objectMapper = new ObjectMapper();
        List<QueryTrackData> queryData = new ArrayList<>();
        try {
            ShoppingOrder byOrderNo = shoppingOrderMapper.getByOrderNo(queryDto.getOrderNo());
            if (ObjectUtil.isNull(byOrderNo)) {
                return HttpResult.fail("订单不存在");
            }
            ShoppingOrderDetail detail = shoppingOrderDetailMapper.getDetail(queryDto.getOrderNo(), queryDto.getSkuId());

//            Object o = redisUtil.get(detail.getShippingCode());
//            if (!ObjectUtil.isNull(o)) {
//                String responseJson = String.valueOf(o);
//                response = objectMapper.readValue(responseJson, Express100DTO.class);// json转对象
//                if (!ObjectUtil.isNull(response)) {
//                    return new HttpResult(response);
//                }
//            }


            QueryTrackReq queryTrackReq = new QueryTrackReq();
            QueryTrackParam queryTrackParam = new QueryTrackParam();
            //快递公司的编码
            queryTrackParam.setCom(detail.getShippingNameCode());
            //快递单号
            queryTrackParam.setNum(detail.getShippingCode());
            queryTrackParam.setResultv2("4");
//            queryTrackParam.setPhone(orderInfoDTO.getReceiverTelephone());
            String param = new Gson().toJson(queryTrackParam);
            log.info("param："+param);
            queryTrackReq.setParam(param);
            queryTrackReq.setCustomer(customer);
            queryTrackReq.setSign(SignUtils.querySign(param ,key,customer));

            log.info("快递查询请求参数："+queryTrackReq.toString());

            IBaseClient baseClient = new QueryTrack();
            com.kuaidi100.sdk.pojo.HttpResult execute = baseClient.execute(queryTrackReq);

            QueryTrackResp queryTrackResp = handleWmsResult(execute, QueryTrackResp.class);
            log.info("快递查询信息返回queryTrackResp："+queryTrackResp.toString());
            if (!"200".equals(queryTrackResp.getStatus())) {
                log.error("快递100APIError" + queryTrackResp.getMessage(),new Throwable());
                return HttpResult.fail(queryTrackResp.getMessage());
            }
            queryData = queryTrackResp.getData();
            String json = objectMapper.writeValueAsString(queryData);// 对象转json
            redisUtil.set(RedisKeys.ORDER_LOGISTICS_KEY + detail.getShippingCode(), json, 3600);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("快递100APIError",e);
            return HttpResult.fail("接口调用失败");
        }
        return new HttpResult(queryData);
    }

    @Nullable
    @SuppressWarnings("all")
    private <T> T handleWmsResult(@NotNull com.kuaidi100.sdk.pojo.HttpResult httpResult, Class<T> clazz) {
        if (httpResult.getStatus() == HttpStatus.SC_OK && StringUtils.isNotEmpty(httpResult.getBody())) {
            String body = httpResult.getBody();
            JSONObject jsonObject = JSON.parseObject(httpResult.getBody());
            if (Objects.nonNull(jsonObject.get("data"))) {
                return JSONObject.toJavaObject(jsonObject, clazz);
            } else if (Objects.nonNull(jsonObject.get("message"))) {
                QueryTrackResp queryTrackResp = JSON.parseObject(httpResult.getBody(), QueryTrackResp.class);
                return JSONObject.toJavaObject(jsonObject, clazz);
            }
            return JSONObject.toJavaObject(jsonObject, clazz);
        }
        return null;
    }

    @Override
    public HttpResult evaluatePage(ComposeQueryDto qto) {
        Page page = qto.getPage();
        page.initPagingData(ShoppingSpuEvaluate.class);
        List<ShoppingSpuEvaluate> evaluates = evaluateMapper.selectAll(qto.getSpuId(),qto.getStarNumStart(),qto.getStarNumEnd());
        page.setResult(evaluates);
        return new HttpResult(page);
    }
    @Override
    public HttpResult evaluate(HttpServletRequest request, ShoppingSpuEvaluate evaluate) {

        ShoppingOrderDetail order = shoppingOrderDetailMapper.getDetail(evaluate.getOrderNo(),evaluate.getSkuId());
        String evaluateId = IdUtil.uuid();
        evaluate.setSpuId(order.getSpuId());
        evaluate.setEvaluateId(evaluateId);
        String userId = tokenUtil.getUserId(request);
        evaluate.setUserId(userId);
        evaluate.setEvaluateDate(new Date());
        evaluateMapper.insert(evaluate);
        spuMapper.updateScore(order.getSpuId());
        if (StringUtils.isNotEmpty(evaluate.getOrderNo())){
            shoppingOrderDetailMapper.hasEvaluate(evaluate.getOrderNo(),evaluate.getSkuId());
        }
        return HttpResult.OK;
    }
}
